package com.zhangfb95.crosschain.infra.util;

import lombok.extern.slf4j.Slf4j;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

@Slf4j
public class AesUtil {

    public static final String DEFAULT_PWD = String.join("", new String[]{"sfe0", "23f_", "9fd&", "fwfl"});

    private static byte[] encryptToBytes(String content, String password) {
        SecretKey key = new SecretKeySpec(password.getBytes(), "AES");
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
            IvParameterSpec ivParameterSpec = new IvParameterSpec(password.getBytes(StandardCharsets.UTF_8));
            cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
            return cipher.doFinal(byteContent);
        } catch (NoSuchAlgorithmException |
                 NoSuchPaddingException |
                 InvalidKeyException |
                 IllegalBlockSizeException |
                 BadPaddingException |
                 InvalidAlgorithmParameterException e) {
            log.error("AES encrypt to bytes failed" + e.getMessage(), e);
        }
        return null;
    }

    private static byte[] decryptToBytes(byte[] content, String password) {
        try {
            SecretKey key = new SecretKeySpec(password.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(password.getBytes(StandardCharsets.UTF_8));
            cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);

            return cipher.doFinal(content);
        } catch (IllegalBlockSizeException |
                 InvalidKeyException |
                 BadPaddingException |
                 NoSuchAlgorithmException |
                 NoSuchPaddingException |
                 InvalidAlgorithmParameterException e) {
            log.error("AES decrypt to bytes failed" + e.getMessage(), e);
        }
        return null;
    }

    public static String encryptToString(String content, String password) {
        byte[] encryptBase64Bytes = encryptToBytes(content, password);
        return encryptBASE64(encryptBase64Bytes);
    }

    public static String encryptBASE64(byte[] key) {
        return Base64.getEncoder().encodeToString(key);
    }

    public static String decryptToString(String content, String password) {
        byte[] decryptBase64Bytes = decryptBASE64(content);
        byte[] decryptBytes = decryptToBytes(decryptBase64Bytes, password);
        if (decryptBytes == null) {
            return null;
        }
        return new String(decryptBytes);
    }

    public static byte[] decryptBASE64(String key) {
        return Base64.getDecoder().decode(key);
    }
}
